// 命令行参数： 是否需要权限、是否开启Cache
import fs from 'fs'
import { PrismaClient as PgClient } from '../../../prisma/generated/uctoo'
require('dotenv').config()
const {  DATABASE_URL } = process.env
const db = new PgClient({
  log: ['query', 'info', 'warn', 'error'],
  datasourceUrl: DATABASE_URL,
});

async function main() {
  const args = process.argv.slice(2); // 去掉数组中的前两个元素
  let dbName = args[0] ? args[0] : 'uctoo';
  const requireUser = args[1] ? args[1] : 'false'
  const cache = args[2] ? args[2] : 'false'

  try {
    // 查询是否存在数据库
    const result = await db.db_info.findMany({
      where: { is_table_hidden: 'NO', table_catalog: dbName },
      distinct: ['table_name'],
      orderBy: { table_name: "asc" }
    })
    console.log("result:", result.length)
    if (result.length === 0) {
      // 不存在，获取数据库信息失败
      console.log(`select db_info fail.`)
    } else {
      const path = process.cwd()
      //存在，获取数据库信息,
      // 从数据取出表信息
      for (const row of result) {
        let tableName = row.table_name;
        const SKIP_TABLES = [];
        if (SKIP_TABLES.includes(tableName)) {
          continue;
        }
        // 首字母小写
        let lowerTableName = convertToCamelCase(tableName)
        // 首字母大写
        const upperTableName = `${lowerTableName.charAt(0).toLocaleUpperCase()}${lowerTableName.slice(1)}`
        console.log('tableName:' + tableName)
        
        // 获取表结构信息和ID字段类型
        const fields = await db.db_info.findMany({
          where: { table_name: tableName, table_catalog: dbName },
          orderBy: { ordinal_position: 'asc' }
        });
        
        const idFieldType = getTableIdFieldType(fields);
        
        const config = {
          service: {
            tpl: `${path}/src/app/services/uctoo/db_entity.ts.tpl`,
            target: `${path}/src/app/services/${dbName}`,
            name: `${tableName}.ts`
          },
          controller: {
            tpl: `${path}/src/app/controllers/uctoo/entity/db_index.ts.tpl`,
            target: `${path}/src/app/controllers/${dbName}/${tableName}`,
            name: `index.ts`
          },
          route: {
            tpl: `${path}/src/app/routes/uctoo/entity/db_index.ts.tpl`,
            target: `${path}/src/app/routes/${dbName}/${tableName}`,
            name: `index.ts`
          }
        }

        createModule("service", config, tableName, lowerTableName, upperTableName, requireUser, cache, dbName, idFieldType)
        createModule("controller", config, tableName, lowerTableName, upperTableName, requireUser, cache, dbName)
        createModule("route", config, tableName, lowerTableName, upperTableName, requireUser, cache, dbName)
        appendControllers(path, tableName, lowerTableName, upperTableName, dbName)
        appendRoutes(path, tableName, lowerTableName, upperTableName, dbName)

      }
    }
  } catch (ex) {
    console.log(ex)
  }

}

function convertToCamelCase(str) {
  return str.toLowerCase().replace(/_(.)/g, function (match, group1) {
    return group1.toUpperCase();
  });
}
// 检测表的ID字段类型
function getTableIdFieldType(fields) {
  const idField = fields.find(field => field.column_name === 'id');
  return idField ? idField.data_type : 'text';
}

function createModule(module, config, tableName, lowerTableName, upperTableName, requestUser, cache, dbName, idFieldType = 'text') {
  const replaceFun = {
    service: (data) => replaceService(data, tableName, lowerTableName, upperTableName, requestUser, cache, dbName, idFieldType),
    controller: replaceController,
    route: replaceRouter,
  }
  const autoCodeStartStr = "//#region AutoCreateCode"
  const autoCodeEndStr = "//#endregion AutoCreateCode"
  const tplPath = config[module].tpl
  const targetPath = config[module].target
  const targetName = config[module].name
  const targetFullName = `${targetPath}/${targetName}`
  if (!fs.existsSync(targetPath)) {
    try {
      fs.mkdirSync(targetPath, { recursive: true });
    } catch (err) {
      console.error(err);
    }
  }
  let tplData = ''
  try {
    const data = fs.readFileSync(tplPath, 'utf8');
    // console.log(data);
    if (data) {
      tplData = replaceFun[module](data, tableName, lowerTableName, upperTableName, requestUser, cache, dbName)
      if (tplData) {
        console.log("fs.existsSync(targetFullName):", fs.existsSync(targetFullName))
        if (fs.existsSync(targetFullName)) {
          const targetData = fs.readFileSync(`${targetFullName}`, 'utf8');
          const targetStart = targetData.indexOf(autoCodeStartStr)
          if (targetStart <= -1) {
            console.log(`targetPath cant not match ${autoCodeStartStr}!${targetFullName}`)
            return
          }
          const targetEnd = targetData.indexOf(autoCodeEndStr)
          if (targetEnd <= -1) {
            console.log(`targetPath cant not match ${autoCodeEndStr}!`)
            return
          }
          if (targetStart >= targetEnd) {
            console.log(`targetPath start>=end,please check!start=${targetStart}, end =${targetEnd} `)
            return
          }
          const headStr = targetData.slice(0, targetStart)
          const footStr = targetData.slice(targetEnd, targetData.length)
          //拆分
          const tplStart = tplData.indexOf(autoCodeStartStr)
          if (tplStart <= -1) {
            console.log(`tplPath cant not match ${autoCodeStartStr}!`)
            return
          }
          const tplEnd = tplData.indexOf(autoCodeEndStr)
          if (tplEnd <= -1) {
            console.log(`tplPath cant not match ${autoCodeEndStr}!`)
            return
          }
          if (tplStart >= tplEnd) {
            console.log(`tplPath start>=end,please check!start=${tplStart}, end =${tplEnd} `)
            return
          }
          const middleStr = tplData.slice(tplStart, tplEnd)
          tplData = `${headStr}${middleStr}${footStr}`
          console.log(tplStart, tplEnd, targetStart, targetEnd)
        }
        console.log('tplData length:', tplData.length)
        // if (module == 'controller') {
        //   tplData = tplData.replace(`} from '../../services/`, `,count${upperTableName}s\r\n} from '../../services/`)
        // }
        fs.writeFileSync(`${targetFullName}`, tplData)
        console.log(`writeFile ${targetFullName} success!`)
      } else {
        console.log(`writeFile ${targetFullName} error! no context`)
      }
    }
  } catch (err) {
    console.error('处理文件出错', err);
  }
}

function replaceService(data, tableName, lowerTableName, upperTableName, requireUser, cache, dbName, idFieldType) {
  // 只需要进行基本的文本替换，不再需要复杂的条件逻辑和正则替换
  let context = data.replace(/Entity/g, upperTableName)
    .replace(/entity/g, lowerTableName)
    .replace(/table_name/g, tableName)
    .replace(/database_name/g, dbName)
    // 修复ID_FIELD_TYPE的语法错误 - 模板中已经有引号，不需要再添加
    .replace(/ID_TYPE_PLACEHOLDER/g, idFieldType);
  
  return context
}
function replaceController(data, tableName, lowerTableName, upperTableName, requireUser, cache, dbName) {
  const context = data.replace(/Entity/g, upperTableName)
    .replace(/entity/g, lowerTableName)
    // .replace(`} from '../../services/table_name';`, `count${upperTableName}s\r\n} from '../../services/table_name';`)
    .replace(/table_name/g, tableName)
    .replace(/database_name/g, dbName)
  return context
}
function replaceRouter(data, tableName, lowerTableName, upperTableName, requireUser, cache, dbName) {
  let context = data.replace(/Entity/g, upperTableName).replace(/entity/g, lowerTableName).replace(/database_name/g, dbName).replace(/table_name/g, tableName)
  if (requireUser == 'true') {
    context = context.replace(/needRequireUser,/g, 'requireUser,')
  } else {
    context = context.replace(/needRequireUser,/g, "")
  }
  if (cache == 'true') {
    context = context.replace(/needCache,/g, 'cache,')
  } else {
    context = context.replace(/needCache,/g, "")
  }
  return context
}

function appendControllers(path, tableName, lowerTableName, upperTableName, dbName) {
  const tplPath = `${path}/src/app/controllers/index.ts`
  const targetPath = `${path}/src/app/controllers`
  // 判断是否有目录，没有要创建
  if (!fs.existsSync(targetPath)) {
    try {
      fs.mkdirSync(targetPath, { recursive: true });
    } catch (err) {
      console.error(err);
    }
  }
  let context = ''
  try {
    const data = fs.readFileSync(tplPath, 'utf8');
    if (data) {
      context = data
    /*  if (data.indexOf(`${dbName}${upperTableName}Controller from`) < 0) {
        context = data.replace('export {', `import ${dbName}${upperTableName}Controller from './${dbName}/${tableName}';\r\nexport {`)
          .replace('};', `  ${dbName}${upperTableName}Controller,\r\n};`)
      } */
      if (context) {
     //   fs.writeFileSync(`${targetPath}/index.ts`, context)
        appendUniqueControllerExport(`${targetPath}/index.ts`, dbName, tableName, upperTableName)
        console.log(`writeFile ${targetPath}/index.ts success!`)
      } else {
        console.log(`writeFile ${targetPath}/index.ts error! no context`)
      }
    }
  } catch (err) {
    console.error('处理文件出错', err);
  }
}

function appendRoutes(path, tableName, lowerTableName, upperTableName, dbName) {
  const tplPath = `${path}/src/app/routes/index.ts`
  const targetPath = `${path}/src/app/routes`
  // 判断是否有目录，没有要创建
  if (!fs.existsSync(targetPath)) {
    try {
      fs.mkdirSync(targetPath, { recursive: true });
    } catch (err) {
      console.error(err);
    }
  }
  let context = ''
  try {
    const data = fs.readFileSync(tplPath, 'utf8');
    if (data) {
      context = data
     /* if (data.indexOf(`/${dbName}${tableName}`) < 0) {
        context = data.replace(/const api_router = new Router/g, `import ${dbName}${lowerTableName}Router from './${dbName}/${tableName}';\r\nconst api_router = new Router`)
          .replace(/export default api_router/g, `api_router.use('/${dbName}/${tableName}', ${dbName}${lowerTableName}Router);\r\nexport default api_router`)
      } */
      if (context) {
       // fs.writeFileSync(`${targetPath}/index.ts`, context)
       appendUniqueRouter(`${targetPath}/index.ts`, dbName, tableName, upperTableName) 
       console.log(`writeFile ${targetPath}/index.ts success!`)
      } else {
        console.log(`writeFile ${targetPath}/index.ts error! no context`)
      }
    }
  } catch (err) {
    console.error('处理文件出错', err);
  }
}

/**
 * 在文件导出块末尾追加新控制器配置
 * @param filePath 目标文件路径
 * @param dbName 数据库名称（如uctoov2）
 * @param tableName 表名（如api_tester_log）
 * @param upperTableName 首字母大写的表名（如ApiTesterLog）
 */
function appendUniqueControllerExport(
  filePath: string,
  dbName: string,
  tableName: string,
  upperTableName: string
) {
  try {
    const content = fs.readFileSync(filePath, 'utf-8');
    const lines = content.split(/\r?\n/);
    
    // 生成控制器配置
    const controllerName = `${dbName}${upperTableName}Controller`;
    const controllerPath = `./${dbName}/${tableName}`;

    // 检查重复配置
    const exists = lines.some(line => 
      line.includes(controllerName) || 
      line.includes(`from '${controllerPath}'`)
    );

    if (exists) {
      console.log(`⏩ 跳过重复控制器: ${controllerName}`);
      return;
    }

    // 处理导入语句（确保追加到最后import之后）
    let lastImportIndex = -1;
    for (let i = lines.length - 1; i >= 0; i--) {
      if (lines[i].trim().startsWith('import ')) {
        lastImportIndex = i;
        break;
      }
    }
    
    if (lastImportIndex >= 0) {
      lines.splice(lastImportIndex + 1, 0, 
        `import ${controllerName} from '${controllerPath}';`);
    } else {
      lines.unshift(`import ${controllerName} from '${controllerPath}';`);
    }
    // 处理导出块（精准定位导出块结尾）
    const exportStartIndex = lines.findIndex(line => 
      line.trim().startsWith('export {')
    );

    if (exportStartIndex >= 0) {
      let exportEndIndex = lines.findIndex(
        (line, idx) => idx >= exportStartIndex && line.includes('}')
      );
      
      if (exportEndIndex >= 0) {
        // 在最后一个导出项后追加逗号和换行
        const lastExportLine = lines[exportEndIndex - 1];
        lines[exportEndIndex - 1] = lastExportLine.endsWith(',') 
          ? `${lastExportLine}\n  ${controllerName}`
          : `${lastExportLine},\n  ${controllerName}`;
      }
    } else {
      // 无导出块时创建新导出
      lines.push(`export { ${controllerName} };`);
    }

    fs.writeFileSync(filePath, lines.join('\n'));
    console.log(`✅ 成功追加控制器: ${controllerName}`);
  } catch (error) {
    console.error('❌ 控制器追加失败:', error.message);
  }
}

/**
 * 向路由文件追加新的路由配置（自动避开最后的export语句）
 * @param filePath 目标文件路径
 * @param dbName 数据库名称（如 uctootest）
 * @param tableName 表名（如 book）
 * @param upperTableName 首字母大写的表名（如 TodoList）
 */
function appendUniqueRouter(
  filePath: string,
  dbName: string,
  tableName: string,
  upperTableName: string
) {
  try {
    const content = fs.readFileSync(filePath, 'utf-8');
    let lines = content.split(/\r?\n/);
    
    // 生成关键语句
    const routerName = `${dbName}${upperTableName}Router`;
    const importLine = `import ${routerName} from './${dbName}/${tableName}';`;
    const routeLine = `api_router.use('/${dbName}/${tableName}', ${routerName});`;

    // 查找固定导出语句位置
    const exportIndex = lines.findIndex(line => 
      line.trim() === 'export default api_router'
    );

    // 验证文件结构
    if (exportIndex === -1) {
      throw new Error('未找到 export default api_router 语句');
    }

    // 检查是否已存在相同配置
    const hasDuplicate = lines.some(line => 
      line.includes(`use('/${dbName}/${tableName}'`) ||
      line.includes(`from './${dbName}/${tableName}'`)
    );

    if (hasDuplicate) {
      console.log(`⏩ 跳过重复路由: /${dbName}/${tableName}`);
      return;
    }

    // 插入导入语句（在最后一个import后）
    const lastImportIndex = lines.reduce((acc, line, index) => 
      line.startsWith('import ') ? index : acc, -1
    );

    if (lastImportIndex >= 0) {
      lines.splice(lastImportIndex + 1, 0, importLine);
    } else {
      lines = [importLine, ...lines];
    }

    // 插入路由配置（在export语句前）
    lines.splice(exportIndex, 0, routeLine);

    fs.writeFileSync(filePath, lines.join('\n'));
    console.log(`✅ 成功添加路由: /${dbName}/${tableName}`);
  } catch (error) {
    console.error('❌ 路由配置追加失败:', error.message);
  }
}

main()